<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>错误分析 - Netty See</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    <style>
        .chart-container {
            position: relative;
            height: 300px;
        }
        .error-record {
            border-left: 4px solid #dc3545;
            margin-bottom: 10px;
        }
        .error-type-badge {
            font-size: 0.8rem;
        }
        .stack-trace {
            font-family: monospace;
            font-size: 0.8rem;
            background-color: #f8f9fa;
            border: 1px solid #dee2e6;
            border-radius: 4px;
            padding: 8px;
            max-height: 200px;
            overflow-y: auto;
        }
    </style>
</head>
<body>
    <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
        <div class="container">
            <a class="navbar-brand" href="/">
                <i class="fas fa-network-wired"></i> Netty See
            </a>
            <div class="navbar-nav ms-auto">
                <a class="nav-link" href="/channels">Channels</a>
                <a class="nav-link" href="/eventloops">Event Loops</a>
                <a class="nav-link" href="/performance">Performance</a>
                <a class="nav-link active" href="/errors">错误分析</a>
            </div>
        </div>
    </nav>

    <div class="container mt-4">
        <div class="row">
            <div class="col-12">
                <div class="d-flex justify-content-between align-items-center mb-4">
                    <h1><i class="fas fa-exclamation-triangle"></i> 错误分析</h1>
                    <div>
                        <button class="btn btn-primary" onclick="refreshErrorData()">
                            <i class="fas fa-sync-alt"></i> 刷新
                        </button>
                        <button class="btn btn-success" onclick="toggleAutoRefresh()">
                            <i class="fas fa-play" id="autoRefreshIcon"></i> 
                            <span id="autoRefreshText">开启自动刷新</span>
                        </button>
                    </div>
                </div>
            </div>
        </div>

        <!-- 错误统计概览 -->
        <div class="row mb-4">
            <div class="col-md-3">
                <div class="card bg-danger text-white">
                    <div class="card-body text-center">
                        <i class="fas fa-exclamation-circle fa-2x mb-2"></i>
                        <div class="h4" id="totalErrors">0</div>
                        <div>总错误数</div>
                    </div>
                </div>
            </div>
            <div class="col-md-3">
                <div class="card bg-warning text-white">
                    <div class="card-body text-center">
                        <i class="fas fa-percentage fa-2x mb-2"></i>
                        <div class="h4" id="errorRate">0.0%</div>
                        <div>错误率</div>
                    </div>
                </div>
            </div>
            <div class="col-md-3">
                <div class="card bg-info text-white">
                    <div class="card-body text-center">
                        <i class="fas fa-list fa-2x mb-2"></i>
                        <div class="h4" id="errorTypes">0</div>
                        <div>错误类型</div>
                    </div>
                </div>
            </div>
            <div class="col-md-3">
                <div class="card bg-secondary text-white">
                    <div class="card-body text-center">
                        <i class="fas fa-desktop fa-2x mb-2"></i>
                        <div class="h4" id="affectedApps">0</div>
                        <div>受影响应用</div>
                    </div>
                </div>
            </div>
        </div>

        <!-- 错误趋势图表 -->
        <div class="row mb-4">
            <div class="col-12">
                <div class="card">
                    <div class="card-header">
                        <h5 class="mb-0">错误趋势 (最近24小时)</h5>
                    </div>
                    <div class="card-body">
                        <div class="chart-container">
                            <canvas id="errorTrendChart"></canvas>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <!-- Top错误类型和应用 -->
        <div class="row mb-4">
            <div class="col-md-6">
                <div class="card">
                    <div class="card-header">
                        <h5 class="mb-0">Top 错误类型</h5>
                    </div>
                    <div class="card-body">
                        <div id="topErrorTypes">
                            <div class="text-center text-muted">
                                <i class="fas fa-spinner fa-spin"></i> 加载中...
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <div class="col-md-6">
                <div class="card">
                    <div class="card-header">
                        <h5 class="mb-0">Top 错误应用</h5>
                    </div>
                    <div class="card-body">
                        <div id="topErrorApps">
                            <div class="text-center text-muted">
                                <i class="fas fa-spinner fa-spin"></i> 加载中...
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <!-- 最近错误记录 -->
        <div class="row">
            <div class="col-12">
                <div class="card">
                    <div class="card-header">
                        <h5 class="mb-0">最近错误记录</h5>
                    </div>
                    <div class="card-body">
                        <div id="recentErrors">
                            <div class="text-center text-muted">
                                <i class="fas fa-spinner fa-spin"></i> 加载中...
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <!-- 错误详情模态框 -->
    <div class="modal fade" id="errorDetailModal" tabindex="-1">
        <div class="modal-dialog modal-lg">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title">错误详情</h5>
                    <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
                </div>
                <div class="modal-body" id="errorDetailContent">
                    <!-- 详情内容将在这里动态加载 -->
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
                </div>
            </div>
        </div>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
    <script>
        let errorTrendChart;
        let isAutoRefresh = false;
        let autoRefreshInterval;

        function initErrorTrendChart() {
            const ctx = document.getElementById('errorTrendChart').getContext('2d');
            errorTrendChart = new Chart(ctx, {
                type: 'line',
                data: {
                    labels: [],
                    datasets: [{
                        label: '错误数',
                        data: [],
                        borderColor: 'rgb(220, 53, 69)',
                        backgroundColor: 'rgba(220, 53, 69, 0.1)',
                        tension: 0.1
                    }, {
                        label: '错误率 (%)',
                        data: [],
                        borderColor: 'rgb(255, 193, 7)',
                        backgroundColor: 'rgba(255, 193, 7, 0.1)',
                        tension: 0.1,
                        yAxisID: 'y1'
                    }]
                },
                options: {
                    responsive: true,
                    maintainAspectRatio: false,
                    scales: {
                        y: {
                            type: 'linear',
                            display: true,
                            position: 'left',
                            beginAtZero: true,
                            title: {
                                display: true,
                                text: '错误数'
                            }
                        },
                        y1: {
                            type: 'linear',
                            display: true,
                            position: 'right',
                            beginAtZero: true,
                            max: 100,
                            title: {
                                display: true,
                                text: '错误率 (%)'
                            },
                            grid: {
                                drawOnChartArea: false,
                            },
                        }
                    }
                }
            });
        }

        function refreshErrorData() {
            // 获取错误统计
            fetch('/api/netty/errors/stats')
                .then(response => response.json())
                .then(data => {
                    updateErrorStats(data);
                })
                .catch(error => {
                    console.error('Failed to get error stats:', error);
                });

            // 获取错误趋势
            fetch('/api/netty/errors/trend?hours=24')
                .then(response => response.json())
                .then(data => {
                    updateErrorTrendChart(data);
                })
                .catch(error => {
                    console.error('Failed to get error trend:', error);
                });

            // 获取Top错误类型
            fetch('/api/netty/errors/top-types?limit=10')
                .then(response => response.json())
                .then(data => {
                    updateTopErrorTypes(data);
                })
                .catch(error => {
                    console.error('Failed to get top error types:', error);
                });

            // 获取Top错误应用
            fetch('/api/netty/errors/top-applications?limit=10')
                .then(response => response.json())
                .then(data => {
                    updateTopErrorApps(data);
                })
                .catch(error => {
                    console.error('Failed to get top error applications:', error);
                });

            // 获取最近错误记录
            fetch('/api/netty/errors/recent?limit=20')
                .then(response => response.json())
                .then(data => {
                    updateRecentErrors(data);
                })
                .catch(error => {
                    console.error('Failed to get recent errors:', error);
                });
        }

        function updateErrorStats(data) {
            document.getElementById('totalErrors').textContent = data.totalErrors || 0;
            document.getElementById('errorRate').textContent = (data.errorRate || 0).toFixed(1) + '%';
            document.getElementById('errorTypes').textContent = Object.keys(data.errorsByType || {}).length;
            document.getElementById('affectedApps').textContent = Object.keys(data.errorsByApplication || {}).length;
        }

        function updateErrorTrendChart(data) {
            const labels = data.map(item => new Date(item.hour).toLocaleTimeString('zh-CN', {hour: '2-digit', minute: '2-digit'}));
            const errorCounts = data.map(item => item.totalErrors);
            const errorRates = data.map(item => item.errorRate);

            errorTrendChart.data.labels = labels;
            errorTrendChart.data.datasets[0].data = errorCounts;
            errorTrendChart.data.datasets[1].data = errorRates;
            errorTrendChart.update();
        }

        function updateTopErrorTypes(data) {
            const container = document.getElementById('topErrorTypes');
            
            if (!data || data.length === 0) {
                container.innerHTML = '<div class="text-muted">暂无错误类型数据</div>';
                return;
            }

            let html = '<div class="list-group list-group-flush">';
            data.forEach((item, index) => {
                html += `
                    <div class="list-group-item d-flex justify-content-between align-items-center">
                        <div>
                            <span class="badge bg-danger me-2">${index + 1}</span>
                            <span class="error-type-badge badge bg-secondary">${item.errorType}</span>
                        </div>
                        <span class="badge bg-primary rounded-pill">${item.count}</span>
                    </div>
                `;
            });
            html += '</div>';
            
            container.innerHTML = html;
        }

        function updateTopErrorApps(data) {
            const container = document.getElementById('topErrorApps');
            
            if (!data || data.length === 0) {
                container.innerHTML = '<div class="text-muted">暂无错误应用数据</div>';
                return;
            }

            let html = '<div class="list-group list-group-flush">';
            data.forEach((item, index) => {
                html += `
                    <div class="list-group-item d-flex justify-content-between align-items-center">
                        <div>
                            <span class="badge bg-warning me-2">${index + 1}</span>
                            <i class="fas fa-desktop me-1"></i>
                            ${item.applicationName}
                        </div>
                        <span class="badge bg-primary rounded-pill">${item.count}</span>
                    </div>
                `;
            });
            html += '</div>';
            
            container.innerHTML = html;
        }

        function updateRecentErrors(data) {
            const container = document.getElementById('recentErrors');
            
            if (!data || data.length === 0) {
                container.innerHTML = '<div class="text-muted">暂无最近错误记录</div>';
                return;
            }

            let html = '';
            data.forEach(error => {
                html += `
                    <div class="card error-record mb-2">
                        <div class="card-body">
                            <div class="row">
                                <div class="col-md-8">
                                    <h6 class="card-title">
                                        <span class="badge bg-danger me-2">${error.errorType}</span>
                                        ${error.errorMessage || 'No message'}
                                        ${error.count > 1 ? `<span class="badge bg-warning ms-2">×${error.count}</span>` : ''}
                                    </h6>
                                    <p class="card-text">
                                        <small class="text-muted">
                                            <i class="fas fa-desktop me-1"></i> ${error.applicationName || 'Unknown'}
                                            <i class="fas fa-plug ms-3 me-1"></i> ${error.channelId}
                                            <i class="fas fa-clock ms-3 me-1"></i> ${new Date(error.timestamp).toLocaleString()}
                                        </small>
                                    </p>
                                </div>
                                <div class="col-md-4 text-end">
                                    <button class="btn btn-sm btn-outline-primary" onclick="showErrorDetail('${error.channelId}', '${error.errorType}', '${error.timestamp}')">
                                        <i class="fas fa-info-circle"></i> 详情
                                    </button>
                                </div>
                            </div>
                        </div>
                    </div>
                `;
            });
            
            container.innerHTML = html;
        }

        function showErrorDetail(channelId, errorType, timestamp) {
            // 查找对应的错误记录
            fetch('/api/netty/errors/recent?limit=100')
                .then(response => response.json())
                .then(data => {
                    const error = data.find(e => 
                        e.channelId === channelId && 
                        e.errorType === errorType && 
                        e.timestamp === timestamp
                    );
                    
                    if (error) {
                        const content = `
                            <div class="row">
                                <div class="col-12">
                                    <h6><i class="fas fa-exclamation-triangle text-danger"></i> 错误信息</h6>
                                    <table class="table table-sm">
                                        <tr><td><strong>错误类型</strong></td><td><span class="badge bg-danger">${error.errorType}</span></td></tr>
                                        <tr><td><strong>错误消息</strong></td><td>${error.errorMessage || 'N/A'}</td></tr>
                                        <tr><td><strong>应用名称</strong></td><td><span class="badge bg-info">${error.applicationName || 'Unknown'}</span></td></tr>
                                        <tr><td><strong>Channel ID</strong></td><td><code>${error.channelId}</code></td></tr>
                                        <tr><td><strong>发生时间</strong></td><td>${new Date(error.timestamp).toLocaleString()}</td></tr>
                                        <tr><td><strong>重复次数</strong></td><td><span class="badge bg-warning">${error.count}</span></td></tr>
                                        <tr><td><strong>远程地址</strong></td><td><code>${error.remoteAddress || 'N/A'}</code></td></tr>
                                        <tr><td><strong>本地地址</strong></td><td><code>${error.localAddress || 'N/A'}</code></td></tr>
                                    </table>
                                </div>
                            </div>
                            ${error.stackTrace ? `
                            <div class="row">
                                <div class="col-12">
                                    <h6><i class="fas fa-code"></i> 堆栈跟踪</h6>
                                    <div class="stack-trace">${error.stackTrace}</div>
                                </div>
                            </div>
                            ` : ''}
                        `;
                        
                        document.getElementById('errorDetailContent').innerHTML = content;
                        new bootstrap.Modal(document.getElementById('errorDetailModal')).show();
                    }
                })
                .catch(error => {
                    console.error('Failed to get error detail:', error);
                });
        }

        function toggleAutoRefresh() {
            if (isAutoRefresh) {
                clearInterval(autoRefreshInterval);
                isAutoRefresh = false;
                document.getElementById('autoRefreshIcon').className = 'fas fa-play';
                document.getElementById('autoRefreshText').textContent = '开启自动刷新';
            } else {
                autoRefreshInterval = setInterval(refreshErrorData, 30000); // 30秒刷新一次
                isAutoRefresh = true;
                document.getElementById('autoRefreshIcon').className = 'fas fa-pause';
                document.getElementById('autoRefreshText').textContent = '关闭自动刷新';
            }
        }

        // 页面加载完成后初始化
        document.addEventListener('DOMContentLoaded', function() {
            initErrorTrendChart();
            refreshErrorData();
        });
    </script>
</body>
</html>